/*
 *------------------------------------------------------------------------------
 * @File      :    gc2093_mipi.c
 * @Date      :    2021-12-22
 * @Author    :    lomboswer <lomboswer@lombotech.com>
 * @Brief     :    Source file for MDP(Media Development Platform).
 *
 * Copyright (C) 2020-2021, LomboTech Co.Ltd. All rights reserved.
 *------------------------------------------------------------------------------
 */
#include "ei_comm_camera.h"
#include "camera_usr.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#define SNS_ID 2093
#define SNS_NAME  "gc2093_mipi"
#define DEV_TYPE MCSI

#define RAW8_FOR_OFFLINE

static VISS_DEV gaVissDev[ISP_MAX_DEV_NUM] = {-1};
static SNS_STATE_S g_sastSns[VISS_MAX_DEV_NUM];
/*
 * 2lane YUV init
 */
static const SNS_REG_S s_aRaw10b1920x108030fps2Lane[] = {
    /* MIPI clk:594Mbps   */
    /* pclk:74.25Mbyte    */
    /* HB:1100*2          */
    /* Linelength:2200    */
    /* Wpclk:297Mbps      */
    /* Rpclk:237.6Mbps    */
    /* row time:29.62us   */
    /* window height:1125 */
    /* size:1920*1080     */

    /****system****/
    {0x03fe, 0xf0},
    {0x03fe, 0xf0},
    {0x03fe, 0xf0},
    {0x03fe, 0x00},
    {0x03f2, 0x00},
    {0x03f3, 0x00},
    {0x03f4, 0x36},
    {0x03f5, 0xc0},
    {0x03f6, 0x0A},
    {0x03f7, 0x01},
    {0x03f8, 0x2c},
    {0x03f9, 0x10},
    {0x03fc, 0x8e},

    /****CISCTL & ANALOG****/
    {0x0087, 0x18},
    {0x00ee, 0x30},
    {0x00d0, 0xbf},

    {0x01a0, 0x00},
    {0x01a4, 0x40},
    {0x01a5, 0x40},
    {0x01a6, 0x40},
    {0x01af, 0x09},

    {0x0001, 0x00},
    {0x0002, 0x02},
    {0x0003, 0x04},
    {0x0004, 0x00},
    {0x0005, 0x04},
    {0x0006, 0x4c},
    {0x0007, 0x00},
    {0x0008, 0x11},
    {0x0009, 0x00},
    {0x000a, 0x02},
    {0x000b, 0x00},
    {0x000c, 0x04},
    {0x000d, 0x04},
    {0x000e, 0x40},
    {0x000f, 0x07},
    {0x0010, 0x8c},
    {0x0013, 0x15},
    {0x0019, 0x0c},
    {0x0041, 0x04},
    {0x0042, 0x65},
    {0x0053, 0x60},
    {0x008d, 0x92},
    {0x0090, 0x00},
    {0x00c7, 0xe1},

    {0x001b, 0x73},
    {0x0028, 0x0d},
    {0x0029, 0x24},
    {0x002b, 0x04},
    {0x002e, 0x23},
    {0x0037, 0x03},
    {0x0043, 0x04},
    {0x0044, 0x38},
    {0x004a, 0x01},
    {0x004b, 0x28},
    {0x0055, 0x38},
    {0x006b, 0x44},
    {0x0077, 0x00},
    {0x0078, 0x20},
    {0x007c, 0xa1},
    {0x00ce, 0x7c},
    {0x00d3, 0xd4},
    {0x00e6, 0x50},

    /*gain*/
    {0x00b6, 0xc0},
    {0x00b0, 0x60},
    {0x00b3, 0x00},
    {0x00b8, 0x01},
    {0x00b9, 0x00},
    {0x00b1, 0x01},
    {0x00b2, 0x00},

    /*isp*/
    {0x0102, 0x89},
    {0x0104, 0x01},
    {0x010f, 0x00},
    {0x0158, 0x00},

    /*dark sun*/
    {0x0123, 0x08},
    {0x0123, 0x00},
    {0x0120, 0x01},
    {0x0121, 0x04},
    {0x0122, 0x65},
    {0x0124, 0x03},
    {0x0125, 0xff},
    {0x0126, 0x3c},
    {0x001a, 0x8c},
    {0x00c6, 0xe0},

    /*blk*/
    {0x0026, 0x30},
    {0x0142, 0x00},
    {0x0149, 0x1e},
    {0x014a, 0x07},
    {0x014b, 0x80},
    {0x0155, 0x00},
    {0x0414, 0x78},
    {0x0415, 0x78},
    {0x0416, 0x78},
    {0x0417, 0x78},
    {0x04e0, 0x18},

    /*window*/
    {0x0192, 0x02},
    {0x0194, 0x03},
    {0x0195, 0x04},
    {0x0196, 0x38},
    {0x0197, 0x07},
    {0x0198, 0x80},
    {0x01b0, 0x01},
    {0x01b1, 0x00},
    {0x01b2, 0x20},
    {0x01b3, 0x00},
    {0x01b4, 0xf0},
    {0x01b5, 0x80},
    {0x01b6, 0x05},
    {0x01b8, 0x01},
    {0x01b9, 0xe0},
    {0x01ba, 0x01},
    {0x01bb, 0x80},

    /****DVP & MIPI****/
    /* {0x0221, 0x20}, */
    /* {0x0222, 0x10}, */
    /* {0x0223, 0x50}, */ /* clk zero tbl */
    /* {0x0228, 0x50}, */
    /* {0x0229, 0x8}, */
    /* {0x022a, 0x03}, */ /* data zero tbl */
    /* {0x0226, 0x03}, */ /* lp_drv tbl */
    /* {0x0227, 0x0F}, */ /*lp_drv tbl */
    {0x019a, 0x06},
    {0x007b, 0x2a},
    {0x0023, 0x2d},
    {0x0201, 0x27},
    {0x0202, 0x56},
    {0x0203, 0x8e}, /* 0xb6,0xce,0x8e modefied by
                     * tbl for sot error 20200220
                     */
    {0x0212, 0x80},
    {0x0213, 0x07},
    {0x0215, 0x12},
    {0x003e, 0x91},
};

/*
 * 2lane YUV init
 */
static const SNS_REG_S s_aRaw10b1920x108025fps2Lane[] = {
    /* MIPI clk:594Mbps   */
    /* pclk:74.25Mbyte    */
    /* HB:1100*2          */
    /* Linelength:2200    */
    /* Wpclk:297Mbps      */
    /* Rpclk:237.6Mbps    */
    /* row time:29.62us   */
    /* window height:1350 */
    /* size:1920*1080     */

    /****system****/
    {0x03fe, 0xf0},
    {0x03fe, 0xf0},
    {0x03fe, 0xf0},
    {0x03fe, 0x00},
    {0x03f2, 0x00},
    {0x03f3, 0x00},
    {0x03f4, 0x36},
    {0x03f5, 0xc0},
    {0x03f6, 0x0A},
    {0x03f7, 0x01},
    {0x03f8, 0x2c},
    {0x03f9, 0x10},
    {0x03fc, 0x8e},

    /****CISCTL & ANALOG****/
    {0x0087, 0x18},
    {0x00ee, 0x30},
    {0x00d0, 0xbf},

    {0x01a0, 0x00},
    {0x01a4, 0x40},
    {0x01a5, 0x40},
    {0x01a6, 0x40},
    {0x01af, 0x09},

    {0x0001, 0x00},
    {0x0002, 0x02},
    {0x0003, 0x04},
    {0x0004, 0x00},
    {0x0005, 0x04},
    {0x0006, 0x4c},
    {0x0007, 0x00},
    {0x0008, 0x11},
    {0x0009, 0x00},
    {0x000a, 0x02},
    {0x000b, 0x00},
    {0x000c, 0x04},
    {0x000d, 0x04},
    {0x000e, 0x40},
    {0x000f, 0x07},
    {0x0010, 0x8c},
    {0x0013, 0x15},
    {0x0019, 0x0c},
    {0x0041, 0x05},
    {0x0042, 0x46},
    {0x0053, 0x60},
    {0x008d, 0x92},
    {0x0090, 0x00},
    {0x00c7, 0xe1},

    {0x001b, 0x73},
    {0x0028, 0x0d},
    {0x0029, 0x24},
    {0x002b, 0x04},
    {0x002e, 0x23},
    {0x0037, 0x03},
    {0x0043, 0x04},
    {0x0044, 0x38},
    {0x004a, 0x01},
    {0x004b, 0x28},
    {0x0055, 0x38},
    {0x006b, 0x44},
    {0x0077, 0x00},
    {0x0078, 0x20},
    {0x007c, 0xa1},
    {0x00ce, 0x7c},
    {0x00d3, 0xd4},
    {0x00e6, 0x50},

    /*gain*/
    {0x00b6, 0xc0},
    {0x00b0, 0x60},
    {0x00b3, 0x00},
    {0x00b8, 0x01},
    {0x00b9, 0x00},
    {0x00b1, 0x01},
    {0x00b2, 0x00},

    /*isp*/
    {0x0102, 0x89},
    {0x0104, 0x01},
    {0x010f, 0x00},
    {0x0158, 0x00},

    /*dark sun*/
    {0x0123, 0x08},
    {0x0123, 0x00},
    {0x0120, 0x01},
    {0x0121, 0x04},
    {0x0122, 0x65},
    {0x0124, 0x03},
    {0x0125, 0xff},
    {0x0126, 0x3c},
    {0x001a, 0x8c},
    {0x00c6, 0xe0},

    /*blk*/
    {0x0026, 0x30},
    {0x0142, 0x00},
    {0x0149, 0x1e},
    {0x014a, 0x07},
    {0x014b, 0x80},
    {0x0155, 0x00},
    {0x0414, 0x78},
    {0x0415, 0x78},
    {0x0416, 0x78},
    {0x0417, 0x78},
    {0x04e0, 0x18},

    /*window*/
    {0x0192, 0x02},
    {0x0194, 0x03},
    {0x0195, 0x04},
    {0x0196, 0x38},
    {0x0197, 0x07},
    {0x0198, 0x80},
    {0x01b0, 0x01},
    {0x01b1, 0x00},
    {0x01b2, 0x20},
    {0x01b3, 0x00},
    {0x01b4, 0xf0},
    {0x01b5, 0x80},
    {0x01b6, 0x05},
    {0x01b8, 0x01},
    {0x01b9, 0xe0},
    {0x01ba, 0x01},
    {0x01bb, 0x80},

    /****DVP & MIPI****/
    /* {0x0221, 0x20}, */
    /* {0x0222, 0x10}, */
    /* {0x0223, 0x50}, */ /* clk zero tbl */
    /* {0x0228, 0x50}, */
    /* {0x0229, 0x8}, */
    /* {0x022a, 0x03}, */ /* data zero tbl */
    /* {0x0226, 0x03}, */ /* lp_drv tbl */
    /* {0x0227, 0x0F}, */ /*lp_drv tbl */
    {0x019a, 0x06},
    {0x007b, 0x2a},
    {0x0023, 0x2d},
    {0x0201, 0x27},
    {0x0202, 0x56},
    {0x0203, 0x8e},     /* 0xb6,0xce,0x8e modefied by
                         * tbl for sot error 20200220
                         */
    {0x0212, 0x80},
    {0x0213, 0x07},
    {0x0215, 0x12},
    {0x003e, 0x91},
};

/*
 * 2lane YUV init
 */
static const SNS_REG_S s_aRaw10b1920x108030fps2Lane2to1[] = {
    /* MIPI clk:792Mbps */
    /* pclk:99Mbyte */
    /* HB:660*2 */
    /* Linelength:2640 */
    /* Wpclk:396Mbps */
    /* Rpclk:198Mbps */
    /* row time:13.3333us */
    /* window height:1250 */
    /* size:1920*1080 */

    /****system****/
    {0x03fe, 0x80},
    {0x03fe, 0x80},
    {0x03fe, 0x80},
    {0x03fe, 0x00},
    {0x03f2, 0x00},
    {0x03f3, 0x00},
    {0x03f4, 0x36},
    {0x03f5, 0xc0},
    {0x03f6, 0x0B},
    {0x03f7, 0x01},
    {0x03f8, 0x58},
    {0x03f9, 0x40},
    {0x03fc, 0x8e},
    /****CISCTL & ANALOG****/
    {0x0087, 0x18},
    {0x00ee, 0x30},
    {0x00d0, 0xbf},
    {0x01a0, 0x00},
    {0x01a4, 0x40},
    {0x01a5, 0x40},
    {0x01a6, 0x40},
    {0x01af, 0x09},
    {0x0001, 0x00},
    {0x0002, 0x02},
    {0x0003, 0x04},
    {0x0004, 0x02},
    {0x0005, 0x02},
    {0x0006, 0x94},
    {0x0007, 0x00},
    {0x0008, 0x11},
    {0x0009, 0x00},
    {0x000a, 0x02},
    {0x000b, 0x00},
    {0x000c, 0x04},
    {0x000d, 0x04},
    {0x000e, 0x40},
    {0x000f, 0x07},
    {0x0010, 0x8c},
    {0x0013, 0x15},
    {0x0019, 0x0c},
    {0x0041, 0x04},
    {0x0042, 0xE2},
    {0x0053, 0x60},
    {0x008d, 0x92},
    {0x0090, 0x00},
    {0x00c7, 0xe1},
    {0x001b, 0x73},
    {0x0028, 0x0d},
    {0x0029, 0x24},
    {0x002b, 0x04},
    {0x002e, 0x23},
    {0x0037, 0x03},
    {0x0043, 0x04},
    {0x0044, 0x20},
    {0x004a, 0x01},
    {0x004b, 0x20},
    {0x0055, 0x30},
    {0x006b, 0x44},
    {0x0077, 0x00},
    {0x0078, 0x20},
    {0x007c, 0xa1},
    {0x00ce, 0x7c},
    {0x00d3, 0xd4},
    {0x00e6, 0x50},
    /*gain*/
    {0x00b6, 0xc0},
    {0x00b0, 0x60},
    /*isp*/
    {0x0102, 0x89},
    {0x0104, 0x01},
    {0x010e, 0x01},
    {0x010f, 0x00},
    {0x0158, 0x00},
    /*dark sun*/
    {0x0123, 0x08},
    {0x0123, 0x00},
    {0x0120, 0x01},
    {0x0121, 0x00},
    {0x0122, 0x10},
    {0x0124, 0x03},
    {0x0125, 0xff},
    {0x0126, 0x3c},
    {0x001a, 0x8c},
    {0x00c6, 0xe0},
    /*blk*/
    {0x0026, 0x30},
    {0x0142, 0x00},
    {0x0149, 0x1e},
    {0x014a, 0x0f},
    {0x014b, 0x00},
    {0x0155, 0x00},
    {0x0414, 0x78},
    {0x0415, 0x78},
    {0x0416, 0x78},
    {0x0417, 0x78},
    {0x0454, 0x78},
    {0x0455, 0x78},
    {0x0456, 0x78},
    {0x0457, 0x78},
    {0x04e0, 0x18},
    /*window*/
    {0x0192, 0x02},
    {0x0194, 0x03},
    {0x0195, 0x04},
    {0x0196, 0x38},
    {0x0197, 0x07},
    {0x0198, 0x80},
    /****DVP & MIPI****/
    //0x0221, 0x2F,//prepare tbl

    {0x019a, 0x06},
    {0x007b, 0x2a},
    {0x0023, 0x2d},
    {0x0201, 0x27},
    {0x0202, 0x56},
    {0x0203, 0x8e},//0xb6,//modefied by tbl for sot error
    {0x0212, 0x80},
    {0x0213, 0x07},
    {0x0215, 0x12},
    {0x003e, 0x91},
    /****HDR EN****/
    {0x0027, 0x71},
    {0x0215, 0x92},
    {0x024d, 0x01},
};
static const SNS_REG_S s_aRaw10b1920x108025fps2Lane2to1[] = {
    /* MIPI clk:792Mbps */
    /* pclk:99Mbyte */
    /* HB:660*2 */
    /* Linelength:2640 */
    /* Wpclk:396Mbps */
    /* Rpclk:198Mbps */
    /* row time:13.3333us */
    /* window height:1250 */
    /* size:1920*1080 */

    /****system****/
    {0x03fe, 0x80},
    {0x03fe, 0x80},
    {0x03fe, 0x80},
    {0x03fe, 0x00},
    {0x03f2, 0x00},
    {0x03f3, 0x00},
    {0x03f4, 0x36},
    {0x03f5, 0xc0},
    {0x03f6, 0x0B},
    {0x03f7, 0x01},
    {0x03f8, 0x58},
    {0x03f9, 0x40},
    {0x03fc, 0x8e},
    /****CISCTL & ANALOG****/
    {0x0087, 0x18},
    {0x00ee, 0x30},
    {0x00d0, 0xbf},
    {0x01a0, 0x00},
    {0x01a4, 0x40},
    {0x01a5, 0x40},
    {0x01a6, 0x40},
    {0x01af, 0x09},
    {0x0001, 0x00},
    {0x0002, 0x02},
    {0x0003, 0x04},
    {0x0004, 0x02},
    {0x0005, 0x02},
    {0x0006, 0x94},
    {0x0007, 0x00},
    {0x0008, 0x11},
    {0x0009, 0x00},
    {0x000a, 0x02},
    {0x000b, 0x00},
    {0x000c, 0x04},
    {0x000d, 0x04},
    {0x000e, 0x40},
    {0x000f, 0x07},
    {0x0010, 0x8c},
    {0x0013, 0x15},
    {0x0019, 0x0c},
    {0x0041, 0x05},
    {0x0042, 0xdc},
    {0x0053, 0x60},
    {0x008d, 0x92},
    {0x0090, 0x00},
    {0x00c7, 0xe1},
    {0x001b, 0x73},
    {0x0028, 0x0d},
    {0x0029, 0x24},
    {0x002b, 0x04},
    {0x002e, 0x23},
    {0x0037, 0x03},
    {0x0043, 0x04},
    {0x0044, 0x20},
    {0x004a, 0x01},
    {0x004b, 0x20},
    {0x0055, 0x30},
    {0x006b, 0x44},
    {0x0077, 0x00},
    {0x0078, 0x20},
    {0x007c, 0xa1},
    {0x00ce, 0x7c},
    {0x00d3, 0xd4},
    {0x00e6, 0x50},
    /*gain*/
    {0x00b6, 0xc0},
    {0x00b0, 0x60},
    /*isp*/
    {0x0102, 0x89},
    {0x0104, 0x01},
    {0x010e, 0x01},
    {0x010f, 0x00},
    {0x0158, 0x00},
    /*dark sun*/
    {0x0123, 0x08},
    {0x0123, 0x00},
    {0x0120, 0x01},
    {0x0121, 0x00},
    {0x0122, 0x10},
    {0x0124, 0x03},
    {0x0125, 0xff},
    {0x0126, 0x3c},
    {0x001a, 0x8c},
    {0x00c6, 0xe0},
    /*blk*/
    {0x0026, 0x30},
    {0x0142, 0x00},
    {0x0149, 0x1e},
    {0x014a, 0x0f},
    {0x014b, 0x00},
    {0x0155, 0x00},
    {0x0414, 0x78},
    {0x0415, 0x78},
    {0x0416, 0x78},
    {0x0417, 0x78},
    {0x0454, 0x78},
    {0x0455, 0x78},
    {0x0456, 0x78},
    {0x0457, 0x78},
    {0x04e0, 0x18},
    /*window*/
    {0x0192, 0x02},
    {0x0194, 0x03},
    {0x0195, 0x04},
    {0x0196, 0x38},
    {0x0197, 0x07},
    {0x0198, 0x80},
    /****DVP & MIPI****/
    //0x0221, 0x2F,//prepare tbl

    {0x019a, 0x06},
    {0x007b, 0x2a},
    {0x0023, 0x2d},
    {0x0201, 0x27},
    {0x0202, 0x56},
    {0x0203, 0x8e},//0xb6,//modefied by tbl for sot error
    {0x0212, 0x80},
    {0x0213, 0x07},
    {0x0215, 0x12},
    {0x003e, 0x91},
    /****HDR EN****/
    {0x0027, 0x71},
    {0x0215, 0x92},
    {0x024d, 0x01},
};


static CAMERA_POWER_ACT_S s_stPowerUpAct[] = {
    {SNS_RESET, SNS_DOWN},
    {SNS_DELAY, 10},
    {SNS_PWDN, SNS_DOWN},
    {SNS_DELAY, 10},
    {SNS_PWDN, SNS_UP},
    {SNS_DELAY, 10},
    {SNS_RESET, SNS_UP},
    {SNS_DELAY, 10},
};

static CAMERA_POWER_ACT_S s_sPowerDownAct[] = {
    {SNS_PWDN, SNS_DOWN},
    {SNS_DELAY, 10},
    {SNS_RESET, SNS_DOWN},
    {SNS_DELAY, 10},
};

static SNS_TYPE_ATTR_S s_astSnsAttr[] = {
    {
        .enSnsType                  = GC2093_MIPI_1920_1080_30FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 297000000,
        .u32Mclock                  = 27000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 74250000,
        .u32Vts                     = 1125,
        .u32Hts                     = 2200,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw10b1920x108030fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b1920x108030fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 594000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = GC2093_MIPI_1920_1080_25FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 297000000,
        .u32Mclock                  = 27000000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 74250000,
        .u32Vts                     = 1350,
        .u32Hts                     = 2200,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 25,
        .astRegCfgs[0].pstRegs      = s_aRaw10b1920x108025fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b1920x108025fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 594000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = GC2093_MIPI_1920_1080_2TO1_30FPS_RAW10,
#ifdef RAW8_FOR_OFFLINE
        .enPixelFormat              = PIX_FMT_RGB_BAYER_8BITS,
        .enRealPFormat              = PIX_FMT_RGB_BAYER_10BITS,
#else
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
#endif
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 27000000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_VC,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 99000000,
        .u32Vts                     = 1250,
        .u32Hts                     = 2640,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw10b1920x108030fps2Lane2to1,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b1920x108030fps2Lane2to1),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 792000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = GC2093_MIPI_1920_1080_2TO1_25FPS_RAW10,
#ifdef RAW8_FOR_OFFLINE
        .enPixelFormat              = PIX_FMT_RGB_BAYER_8BITS,
        .enRealPFormat              = PIX_FMT_RGB_BAYER_10BITS,
#else
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
#endif
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 27000000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_VC,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 99000000,
        .u32Vts                     = 1500,
        .u32Hts                     = 2640,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 25,
        .astRegCfgs[0].pstRegs      = s_aRaw10b1920x108025fps2Lane2to1,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw10b1920x108025fps2Lane2to1),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 792000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
};

static int CAMERA_SetI2cInfo(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    if (pstSnsState->stI2cInfo.fd > 0) {
        return EI_SUCCESS;
    }

    pstSnsState->stI2cInfo.u8RegBits = 16;
    pstSnsState->stI2cInfo.u8ValBits = 8;
    pstSnsState->stI2cInfo.u16I2cBusNum = 4;
    //pstSnsState->stI2cInfo.u16I2cDevAddr = 0x7e; /* sensor pin C6 pull up */
    pstSnsState->stI2cInfo.u16I2cDevAddr = 0x37; /* sensor pin C6 pull down */
    pstSnsState->pcName = SNS_NAME;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_Detect(VISS_DEV VissDev)
{

    EI_U8 u8Tmp[2];
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U16 u16Id;
    SNS_STATE_S *pstSnsState = EI_NULL;
    I2C_INFO_S *pstI2cInfo = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;

    CAMERA_CHECK_POINTER(pstI2cInfo->pfnReadReg);
    s32Ret = pstI2cInfo->pfnReadReg(pstSnsState, 0x03f0, &u8Tmp[0]);
    if (s32Ret != 0) {
        PRT_VISS_ERR("tmp[0]=%x\n", u8Tmp[0]);
        return EI_FAILURE;
    }
    s32Ret = pstI2cInfo->pfnReadReg(pstSnsState, 0x03f1, &u8Tmp[1]);
    if (s32Ret != 0) {
        PRT_VISS_ERR("tmp[0]=%x,tmp[1]=%x\n", u8Tmp[0], u8Tmp[1]);
        return EI_FAILURE;
    }

    u16Id = (u8Tmp[0] << 8) | u8Tmp[1];
    PRT_VISS_INFO("id: 0x%04x.\n", u16Id);

    if (u16Id != 0x2093) {
        PRT_VISS_ERR("ID wrong! (0x%04x != 0x2093)\n", u16Id);
        return EI_FAILURE;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_Stream(VISS_DEV dev, EI_BOOL bOn)
{
    PRT_VISS_INFO("%s dev : %d CAMERA_Stream*******%d\n", SNS_NAME, dev, bOn);
    return EI_SUCCESS;
}

/* The following functions can be modified as needed */

static int CAMERA_I2cInit(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    int ret = EI_SUCCESS;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    ret = CAMERA_SetI2cInfo(dev);
    CAMERA_CHECK_SUCCESS(ret);

    ret = CAMERA_I2C_Reg_Ops(&pstSnsState->stI2cInfo);
    CAMERA_CHECK_SUCCESS(ret);

    return EI_SUCCESS;
}

static int CAMERA_I2cExit(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_PowerUp(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    CAMERA_SensorPowerUp(VissDev, pstSnsState);

    return 0;
}

static EI_S32 CAMERA_PowerDown(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    CAMERA_SensorPowerDown(VissDev, pstSnsState);

    return 0;
}

static EI_S32 CAMERA_Init(VISS_DEV dev)
{
    EI_U32 j;
    const SNS_TYPE_ATTR_S *pstSnsType;
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret;
    I2C_INFO_S *pstI2cInfo = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;

    pstSnsType = pstSnsState->pstSnsAttr;
    for (j = 0; j < MAX_COF; j++) {
        s32Ret = pstSnsState->stI2cInfo.pfnwriteRegList(pstSnsState,
                pstSnsType->astRegCfgs[j].pstRegs, pstSnsType->astRegCfgs[j].u32RegsCnt);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("%s writeRegList err\n", SNS_NAME);
            return s32Ret;
        }
    }

    if (pstSnsType->enSnsType == GC2093_MIPI_1920_1080_25FPS_RAW10) {
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0041, 0x0b);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0042, 0xb8);
        if (s32Ret != 0) {
            PRT_VISS_ERR("CAMERA_Init error\n");
            return s32Ret;
        }
    }

    if (pstSnsType->enSnsType == GC2093_MIPI_1920_1080_2TO1_25FPS_RAW10) {
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0041, 0x05);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0042, 0xdc);
        if (s32Ret != 0) {
            PRT_VISS_ERR("CAMERA_Init error\n");
            return s32Ret;
        }
    }

    PRT_VISS_INFO("%s writeRegList success\n", SNS_NAME);

    return s32Ret;
}

static void CAMERA_Exit(VISS_DEV dev)
{
    CAMERA_I2cExit(dev);

    return;
}

static EI_S32 CAMERA_SetImageMode(VISS_DEV dev, SNS_TYPE_E enSnsType)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstSnsState->enSnsType = enSnsType;
    pstSnsState->bSyncInit = EI_FALSE;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_EnumSnstype(VISS_DEV VissDev, EI_U32 u32Index, SNS_TYPE_E *peSnstype)
{
    const SNS_TYPE_ATTR_S *pstSnsType;

    if (u32Index >= ARRAY_SIZE(s_astSnsAttr))
        return EN_ERR_NO_FOUND;

    pstSnsType = &s_astSnsAttr[u32Index];

    *peSnstype = pstSnsType->enSnsType;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_SetFrameRate(VISS_DEV VissDev, EI_FLOAT f32Fps)
{
    I2C_INFO_S *pstI2cInfo = EI_NULL;
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Pclk, u32Hts, u32Vts;

    SNS_GET_CTX(VissDev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;
    u32Pclk = pstSnsState->pstSnsAttr->u32Pclk;
    u32Hts = pstSnsState->pstSnsAttr->u32Hts;

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {
        if (pstSnsState->pstSnsAttr->u32FrameRate < f32Fps || 1 > f32Fps) {
            cprintf("1 <= set fps <= %d, set fps: %f\n", pstSnsState->pstSnsAttr->u32FrameRate, f32Fps);
            f32Fps = pstSnsState->pstSnsAttr->u32FrameRate;
        }

        u32Vts = u32Pclk / u32Hts / f32Fps;

        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0041, u32Vts >> 8);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0042, u32Vts);

        if (s32Ret != 0) {
            cprintf("CAMERA_Init error\n");
            return s32Ret;
        }
    } else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_2TO1_FRAME) {
        if (pstSnsState->pstSnsAttr->u32FrameRate < f32Fps || 1 > f32Fps) {
            cprintf("1 <= set fps <= %d, set fps: %f\n", pstSnsState->pstSnsAttr->u32FrameRate, f32Fps);
            f32Fps = pstSnsState->pstSnsAttr->u32FrameRate;
        }

        u32Vts = u32Pclk / u32Hts / f32Fps;

        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0041, u32Vts >> 8);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x0042, u32Vts);

        if (s32Ret != 0) {
            cprintf("CAMERA_Init error\n");
            return s32Ret;
        }
    } else {
        return EN_ERR_NOT_SUPPORT;
    }

    pstSnsState->pstSnsAttr->u32Vts = u32Vts;

    return EI_SUCCESS;

}

static EI_S32 CAMERA_InitSensorExpFunction(SENSOR_EXP_FUNC_S *pstSensorExpFunc)
{
    CAMERA_CHECK_POINTER(pstSensorExpFunc);

    memset(pstSensorExpFunc, 0, sizeof(SENSOR_EXP_FUNC_S));

    pstSensorExpFunc->pfnSensorPowerUp  = CAMERA_PowerUp;
    pstSensorExpFunc->pfnSensorPowerDown = CAMERA_PowerDown;
    pstSensorExpFunc->pfnSensorDetect   = CAMERA_Detect;
    pstSensorExpFunc->pfnSensorInit     = CAMERA_Init;
    pstSensorExpFunc->pfnSensorStream   = CAMERA_Stream;
    pstSensorExpFunc->pfnSensorExit     = CAMERA_Exit;
    pstSensorExpFunc->pfnSensorSetImageMode   = CAMERA_SetImageMode;
    pstSensorExpFunc->pfnSensorEnumSnstype   = CAMERA_EnumSnstype;
    pstSensorExpFunc->pfnSensorSetFrameRate   = CAMERA_SetFrameRate;
    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetAeDefault(ISP_DEV dev, AE_SENSOR_DEFAULT_S *pstAeSnsDft)
{

    CAMERA_CHECK_POINTER(pstAeSnsDft);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_SetFps(ISP_DEV dev, EI_FLOAT f32Fps, AE_SENSOR_DEFAULT_S *pstAeSnsDft)
{
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    CAMERA_CHECK_POINTER(pstAeSnsDft);

    return CAMERA_SetFrameRate(Dev, f32Fps);
}

static EI_S32 CAMERA_SetExpTime(ISP_DEV dev, EI_FLOAT *afIntTime)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Pclk, u32Hts, u32Vts, u32Vmax;
    EI_U32 shutter_time;
    EI_U32 lexp, mexp;
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    SNS_GET_CTX(Dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);
    CAMERA_CHECK_POINTER(afIntTime);
    pstSnsState->afIntTime[0] = afIntTime[0];
    pstSnsState->afIntTime[1] = afIntTime[1];
    pstSnsState->afIntTime[2] = afIntTime[2];
    pstSnsState->afIntTime[3] = afIntTime[3];
    pstSnsState->IspDev = dev;
    CAMERA_CHECK_POWERON(pstSnsState);

    u32Pclk = pstSnsState->pstSnsAttr->u32Pclk;
    u32Hts = pstSnsState->pstSnsAttr->u32Hts;
    u32Vts = pstSnsState->pstSnsAttr->u32Vts;
    if ((u32Pclk == 0) || (u32Hts == 0) || (u32Vts == 0)) {
        PRT_VISS_ERR("error! u32Pclk %d, u32Hts %d, u32Vts %d\n", u32Pclk, u32Hts, u32Vts);
        return EI_FAILURE;
    }

    /* afIntTime[0] long/medium/short/vshort exptime (s) */
    shutter_time = afIntTime[0] * u32Pclk / u32Hts;

    //printf("exp_time: %d, %f(s)!\n", shutter_time, afIntTime[0]);

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {
        if (shutter_time > u32Vts) {
            u32Vmax = shutter_time;
        } else {
            u32Vmax = u32Vts;
        }

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0041, u32Vmax >> 8);
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0042, u32Vmax);

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0003, ((shutter_time >> 8) & 0x3f));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0004, ((shutter_time >> 0) & 0xff));
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("\n");
        }
    }  else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_2TO1_FRAME) {
    if (afIntTime[1] < 1)
            afIntTime[1] = 8;

        lexp = shutter_time / (afIntTime[1] + 1) * afIntTime[1];
        mexp = shutter_time / (afIntTime[1] + 1);

        if (pstSnsState->pstSnsAttr->enSnsType == GC2093_MIPI_1920_1080_2TO1_30FPS_RAW10) {
            if (lexp < 1)
               lexp = 1;

            if (lexp + mexp > 1234) { //vts:1250 lexp + mexp < vts - 16 = 1234
               lexp = 1234 / (afIntTime[1] + 1) * afIntTime[1];
               mexp = lexp / afIntTime[1];
            }

            if (mexp > 134) { //vb = vts - window height - 20 = 1250 - 1088 -20 = 142, mexp < vb-8 = 142 - 8 = 134
               mexp = 134;
               lexp = mexp * afIntTime[1];
            }
       } else if (pstSnsState->pstSnsAttr->enSnsType == GC2093_MIPI_1920_1080_2TO1_25FPS_RAW10) {
           if (lexp < 1)
               lexp = 1;

           if (lexp + mexp > 1484) { //vts:1500 lexp + mexp < vts - 16 = 1484
               lexp = 1484 / (afIntTime[1] + 1) * afIntTime[1];
               mexp = lexp / afIntTime[1];
           }

           if (mexp > 384) { //vb = vts - window height - 20 = 1500 - 1088 - 20 = 392, mexp < vb-8 = 392 - 8 = 384
               mexp = 384;
               lexp = mexp * afIntTime[1];
           }
      }

      s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0003, ((lexp >> 8) & 0x3f));
      s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0004, ((lexp >> 0) & 0xff));

      s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0001, ((mexp >> 8) & 0x3f));
      s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x0002, ((mexp)&0xff));

      shutter_time = lexp;
    }

    afIntTime[0] = (EI_FLOAT)(shutter_time) * u32Hts / u32Pclk;
    if (afIntTime[0] < 0.00001)
        afIntTime[0] = 0.00001;

    return s32Ret;
}

static EI_U32 reg_val_table[25][8] = {
    {0x00, 0x00, 0x01, 0x00, 0x68, 0x07, 0x00, 0xf8},
    {0x00, 0x10, 0x01, 0x0c, 0x68, 0x07, 0x00, 0xf8},
    {0x00, 0x20, 0x01, 0x1b, 0x6c, 0x07, 0x00, 0xf8},
    {0x00, 0x30, 0x01, 0x2c, 0x6c, 0x07, 0x00, 0xf8},
    {0x00, 0x40, 0x01, 0x3f, 0x7c, 0x07, 0x00, 0xf8},
    {0x00, 0x50, 0x02, 0x16, 0x7c, 0x07, 0x00, 0xf8},
    {0x00, 0x60, 0x02, 0x35, 0x7c, 0x08, 0x00, 0xf9},
    {0x00, 0x70, 0x03, 0x16, 0x7c, 0x0b, 0x00, 0xfc},
    {0x00, 0x80, 0x04, 0x02, 0x7c, 0x0d, 0x00, 0xfe},
    {0x00, 0x90, 0x04, 0x31, 0x7c, 0x0f, 0x08, 0x00},
    {0x00, 0xa0, 0x05, 0x32, 0x7c, 0x11, 0x08, 0x02},
    {0x00, 0xb0, 0x06, 0x35, 0x7c, 0x14, 0x08, 0x05},
    {0x00, 0xc0, 0x08, 0x04, 0x7c, 0x16, 0x08, 0x07},
    {0x00, 0x5a, 0x09, 0x19, 0x7c, 0x18, 0x08, 0x09},
    {0x00, 0x83, 0x0b, 0x0f, 0x7c, 0x1b, 0x08, 0x0c},
    {0x00, 0x93, 0x0d, 0x12, 0x7c, 0x1e, 0x08, 0x0f},
    {0x00, 0x84, 0x10, 0x00, 0x7c, 0x22, 0x08, 0x13},
    {0x00, 0x94, 0x12, 0x3a, 0x7c, 0x26, 0x08, 0x17},
    {0x00, 0x5d, 0x1a, 0x02, 0x7c, 0x30, 0x08, 0x21},
    {0x00, 0x9b, 0x1b, 0x20, 0x7c, 0x30, 0x08, 0x21},
    {0x00, 0x8c, 0x20, 0x0f, 0x7c, 0x35, 0x08, 0x26},
    {0x00, 0x9c, 0x26, 0x07, 0x7c, 0x3b, 0x08, 0x2c},
    {0x00, 0xB6, 0x36, 0x21, 0x7c, 0x43, 0x08, 0x34},
    {0x00, 0xad, 0x37, 0x3a, 0x7c, 0x43, 0x08, 0x34},
    {0x00, 0xbd, 0x3d, 0x02, 0x7c, 0x43, 0x08, 0x34},
};

EI_U32 level_table[26] = {
    64,
    75,
    90,
    105,
    122,
    142,
    167,
    193,
    223,
    257,
    299,
    346,
    397,
    444,
    523,
    607,
    700,
    817,
    1131,
    1142,
    1334,
    1568,
    2195,
    2637,
    3121,
    0xffff,
};

static EI_S32 CAMERA_SetGain(ISP_DEV dev, EI_FLOAT fGain)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    //EI_U32 u32Gain;
    VISS_DEV Dev;
    EI_U32 again, dgain, analog_index;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    SNS_GET_CTX(Dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);
    pstSnsState->fGain = fGain;
    CAMERA_CHECK_POWERON(pstSnsState);

     if (fGain < 1)
        fGain = 1;

    //printf("gain: %f!\n", fGain);

    fGain = fGain * 64;

    if (fGain < 64)
        fGain = 64;
    if (fGain > 48 * 64)
        fGain = 48 * 64;

    analog_index = 0;
    while (analog_index < 26) {
        if (fGain < level_table[analog_index])
            break;
        analog_index++;
    }

   dgain = ((fGain * 1000 / level_table[analog_index - 1]) * 64) / 1000;
   again = analog_index - 1;

    //again
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00b4, reg_val_table[again][0]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00b3, reg_val_table[again][1]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00b8, reg_val_table[again][2]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00b9, reg_val_table[again][3]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00ce, reg_val_table[again][4]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00c2, reg_val_table[again][5]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00cf, reg_val_table[again][6]);
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00d9, reg_val_table[again][7]);

    //dgain
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00b1, (dgain >> 6));
    s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x00b2, ((dgain & 0x3f)<<2));

    if (s32Ret != EI_SUCCESS) {
        PRT_VISS_ERR("\n");
    }

    return s32Ret;
}

static EI_S32 CAMERA_InitAeExpFunction(AE_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
    CAMERA_CHECK_POINTER(pstExpFuncs);

    memset(pstExpFuncs, 0, sizeof(AE_SENSOR_EXP_FUNC_S));

    pstExpFuncs->pfnGetAeDefault    = CAMERA_GetAeDefault;
    pstExpFuncs->pfnSetFps          = CAMERA_SetFps;
    pstExpFuncs->pfnSetExpTime      = CAMERA_SetExpTime;
    pstExpFuncs->pfnSetGain         = CAMERA_SetGain;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetAwbDefault(ISP_DEV dev, AWB_SENSOR_DEFAULT_S *pstAwbSnsDft)
{
    CAMERA_CHECK_POINTER(pstAwbSnsDft);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_InitAwbExpFunction(AWB_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
    CAMERA_CHECK_POINTER(pstExpFuncs);

    memset(pstExpFuncs, 0, sizeof(AWB_SENSOR_EXP_FUNC_S));
    pstExpFuncs->pfnGetAwbDefault = CAMERA_GetAwbDefault;

    return EI_SUCCESS;
}

/****************************************************************************
 * callback structure                                                       *
 ****************************************************************************/

static EI_S32 CAMERA_CtxInit(VISS_DEV dev)
{
    SNS_STATE_S *pastSnsStateCtx = EI_NULL;

    SNS_GET_CTX(dev, pastSnsStateCtx);

    CAMERA_CHECK_POINTER(pastSnsStateCtx);

    memset(pastSnsStateCtx, 0, sizeof(SNS_STATE_S));

    pastSnsStateCtx->pstPowerUpAct      = s_stPowerUpAct;
    pastSnsStateCtx->pstPowerDownAct    = s_sPowerDownAct;
    pastSnsStateCtx->u8PwrUpActs        = ARRAY_SIZE(s_stPowerUpAct);
    pastSnsStateCtx->u8PwrDnActs        = ARRAY_SIZE(s_sPowerDownAct);

    return EI_SUCCESS;
}

static EI_VOID CAMERA_CtxExit(VISS_DEV dev)
{
    return ;
}

static EI_S32 CAMERA_RegisterVissCallback(VISS_DEV dev, SNS_TYPE_E enType)
{
    EI_S32 s32Ret;
    SENSOR_S stSns = {0};
    EI_U32 i;
    SNS_STATE_S *pstSnsState = EI_NULL;

    s32Ret = CAMERA_CtxInit(dev);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    SNS_GET_CTX(dev, pstSnsState);

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsState->pstSnsAttr = &s_astSnsAttr[i];
            break;
        }
    }

    pstSnsState->enSnsType = enType;
    pstSnsState->Dev = dev;

    if (i >= ARRAY_SIZE(s_astSnsAttr)) {
        PRT_VISS_ERR("%s does not support this chn configuration", SNS_NAME);
        return EI_FAILURE;
    }

    s32Ret = CAMERA_I2cInit(dev);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    stSns.stSnsAttrInfo.eSensorId = SNS_ID;
    stSns.stSnsAttrInfo.enDevType = DEV_TYPE;
    stSns.stSnsAttrInfo.pstSns = pstSnsState;

    s32Ret  = CAMERA_InitSensorExpFunction(&stSns.stSnsAttrInfo.stSnsExp);
    s32Ret |= VISS_SensorRegCallBack(dev, &stSns);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s sensor register callback function failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret = CAMERA_OpenI2c(pstSnsState);
    CAMERA_CHECK_SUCCESS(s32Ret);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_UnregisterVissCallback(VISS_DEV dev)
{
    EI_S32 s32Ret;
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);

    s32Ret = CAMERA_ExitI2c(pstSnsState);
    CAMERA_CHECK_SUCCESS(s32Ret);

    s32Ret = VISS_SensorUnRegCallBack(dev, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s sensor unregister callback function failed!\n", SNS_NAME);
        return s32Ret;
    }

    CAMERA_CtxExit(dev);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_RegisterIspCallback(VISS_DEV Dev, ISP_DEV dev, ISP_3ALIB_S *pstAeLib, ISP_3ALIB_S *pstAwbLib)
{
    EI_S32 s32Ret;
    AE_SENSOR_REGISTER_S  stAeRegister;
    AWB_SENSOR_REGISTER_S stAwbRegister;

    CAMERA_CHECK_POINTER(pstAeLib);
    CAMERA_CHECK_POINTER(pstAwbLib);

    SNS_SET_ISP_TO_VISS(dev, Dev);

    stAeRegister.SnsId = SNS_ID;
    stAwbRegister.SnsId = SNS_ID;

    s32Ret  = CAMERA_InitAeExpFunction(&stAeRegister.stSnsExp);
    s32Ret |= EI_MI_AE_SensorRegCallBack(dev, pstAeLib, &stAeRegister);

    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s register callback function to ae lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret  = CAMERA_InitAwbExpFunction(&stAwbRegister.stSnsExp);
    s32Ret |= EI_MI_AWB_SensorRegCallBack(dev, pstAwbLib, &stAwbRegister);

    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s register callback function to awb lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_UnregisterIspCallback(ISP_DEV dev, ISP_3ALIB_S *pstAeLib, ISP_3ALIB_S *pstAwbLib)
{
    EI_S32 s32Ret;

    CAMERA_CHECK_POINTER(pstAeLib);
    CAMERA_CHECK_POINTER(pstAwbLib);

    s32Ret = EI_MI_AE_SensorUnRegCallBack(dev, pstAeLib, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s unregister callback function to ae lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret = EI_MI_AWB_SensorUnRegCallBack(dev, pstAwbLib, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s unregister callback function to awb lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetVissDevAttrBySns(SNS_TYPE_E enType,
    VISS_DEV_ATTR_S *pstVissDevAttr)
{
    EI_U32 i;
    const SNS_TYPE_ATTR_S *pstSnsType;

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsType = &s_astSnsAttr[i];
            pstVissDevAttr->stSize          = pstSnsType->stSize;
            pstVissDevAttr->enWorkMode      = pstSnsType->enWorkMode;
            pstVissDevAttr->mClock          = pstSnsType->u32Mclock;
            pstVissDevAttr->enPixelFormat   = pstSnsType->enPixelFormat;
            pstVissDevAttr->enRealPFormat   = pstSnsType->enRealPFormat;
            pstVissDevAttr->enWdrMode       = pstSnsType->enWdrMode;
            pstVissDevAttr->enIspWdrMode    = pstSnsType->enIspWdrMode;
            pstVissDevAttr->enRgbSeq        = pstSnsType->enRgbSeq;
            pstVissDevAttr->u32ModuleClk    = pstSnsType->u32ModuleClk;
            pstVissDevAttr->u32Fps          = pstSnsType->u32FrameRate;
            pstVissDevAttr->u32IspClk       = pstSnsType->u32IspClk;
            pstVissDevAttr->u32IppuClk      = pstSnsType->u32IppuClk;
            pstVissDevAttr->pcSnsName       = SNS_NAME;
            pstVissDevAttr->stDevCfg        = pstSnsType->stDevCfg;

            return EI_SUCCESS;
        }
    }

    PRT_VISS_ERR("%s does not support this dev configuration", SNS_NAME);

    return EI_FAILURE;
}

static EI_S32 CAMERA_GetVissChnAttrBySns(SNS_TYPE_E enType,
    VISS_CHN_ATTR_S *pstVissChnAttr)
{
    EI_U32 i;
    const SNS_TYPE_ATTR_S *pstSnsType;

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsType = &s_astSnsAttr[i];
            pstVissChnAttr->stSize           = pstSnsType->stSize;
            pstVissChnAttr->enPixelFormat    = pstSnsType->enPixelFormat;
            pstVissChnAttr->stFrameRate.s32SrcFrameRate      = pstSnsType->u32FrameRate;
            return EI_SUCCESS;
        }
    }

    PRT_VISS_ERR("%s does not support this chn configuration", SNS_NAME);

    return EI_FAILURE;

}

CAMERA_OBJ_S stCameraGc2093mipiObj = {
    .pfnRegisterVissCallback    = CAMERA_RegisterVissCallback,
    .pfnUnRegisterVissCallback  = CAMERA_UnregisterVissCallback,
    .pfnRegisterIspCallback     = CAMERA_RegisterIspCallback,
    .pfnUnRegisterIspCallback   = CAMERA_UnregisterIspCallback,
    .pfnGetVissDevAttrBySns     = CAMERA_GetVissDevAttrBySns,
    .pfnGetVissChnAttrBySns     = CAMERA_GetVissChnAttrBySns,
};

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

